﻿using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using LFSRecord2.Model;
using LFSRecord2.Model.UserActions;

namespace LFSRecord2.View.TimelineStructures
{
    /// <summary>
    /// Interaction logic for StringValueEditControl.xaml
    /// </summary>
    public partial class StringValueEditControl : UserControl, INotifyPropertyChanged
    {
        public string ValueName = "";
        public int MaxLength = 63;

        public static DependencyProperty ValueProperty = DependencyProperty.Register(
              "Value",
              typeof(string),
              typeof(StringValueEditControl),
              new FrameworkPropertyMetadata(new PropertyChangedCallback(handleValueChange))
            );
        public string Value
        {
            get
            {
                return (string)GetValue(ValueProperty);
            }
            set
            {
                SetValue(ValueProperty, value);
                OnPropertyChanged(ValueName);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                var e = new PropertyChangedEventArgs(propertyName);
                handler(this, e);
            }
        }

        public StringValueEditControl()
        {
            InitializeComponent();
        }

        static void handleValueChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((StringValueEditControl)d).writeLabelValue();
        }

        public void writeLabelValue()
        {
            // Check length of the text. Can be max 120px wide.
            string str = "";
            FormattedText formattedText;

            for (int a = 0; a < Value.Length; a++)
            {
                str = str + "" + Value.ElementAt(a);
                
                formattedText = new FormattedText(
                    str,
                    CultureInfo.InvariantCulture,
                    FlowDirection.LeftToRight,
                    new Typeface("Segoe UI"),
                    10,
                    Brushes.Black);
                if (formattedText.Width > 105 && Value.Length > a + 2)
                {
                    str = str + "...";
                    break;
                }
            }

            ValueLabel.Text = (str.Length == 0) ? "..." : str;
        }
        
        string _origValue;
        private void ValueLabel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
            _origValue = Value;
            
            // Show input box for keyboard input
            InputBox.Text = Value;
            InputBox.Visibility = Visibility.Visible;
            InputBox.SelectAll();
            InputBox.Focus();

            InputBox.MaxLength = MaxLength;
            InputBox.TextChanged += InputBox_TextChanged;
            InputBox.KeyDown += InputBox_KeyDown;
            Application.Current.MainWindow.PreviewMouseDown += Global_MouseDown;
        }

        private void InputBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            // Validate the text
            if (InputBox.Text.Length > MaxLength)
                InputBox.Text = InputBox.Text.Substring(0, MaxLength);
        }

        private void InputBox_KeyDown(object sender, KeyEventArgs e)
        {
            //Debug.WriteLine("kb input : " + e.Key);

            if (e.Key == Key.Enter)
            {
                e.Handled = true;
                if (InputBox.Text.Length > MaxLength)
                    InputBox.Text = InputBox.Text.Substring(0, MaxLength); 
                Value = InputBox.Text;
                SubmitUserAction(_origValue, Value);
                LfsRecordController.CreateUndoLevel();
                HideInputBox();
            }
            else if (e.Key == Key.Tab)
            {
                e.Handled = true;
            }
            else if (e.Key == Key.Escape)
            {
                e.Handled = true;
                HideInputBox();
            }
        }

        private void HideInputBox()
        {
            Application.Current.MainWindow.PreviewMouseDown -= Global_MouseDown;
            InputBox.TextChanged -= InputBox_TextChanged;
            InputBox.KeyDown -= InputBox_KeyDown;
            InputBox.Visibility = Visibility.Collapsed;
            Application.Current.MainWindow.Focus();
        }

        private void Global_MouseDown(object sender, MouseButtonEventArgs e)
        {
            //Debug.WriteLine("Sender type : " + e.OriginalSource.GetType());
            if (e.OriginalSource.GetType().ToString() != "System.Windows.Controls.TextBoxView")
            {
                if (InputBox.Text.Length > MaxLength)
                    InputBox.Text = InputBox.Text.Substring(0, MaxLength);
                Value = InputBox.Text;
                SubmitUserAction(_origValue, Value);
                LfsRecordController.CreateUndoLevel();
                HideInputBox();
            }
        }

        private void SubmitUserAction(string origValue, string newValue)
        {
            CompLayerPropertyBase prop = (CompLayerPropertyBase)DataContext;

            int keyFrameIndex = -1;
            CustomKeyFrame kf = prop.GetKeyAtTime(LfsRecordController.FrameIndex);
            if (kf != null)
            {
                keyFrameIndex = kf.KeyFrameIndex;
            }

            LfsRecordController.RecordUserAction(new UserActionKeyFrameStringValueChanged()
            {
                LayerIndex = prop.ParentLayer.LayerIndex,
                PropertyIndex = prop.PropertyIndex,
                KeyFrameIndex = keyFrameIndex,
                OldValue = origValue,
                NewValue = newValue
            });
        }
    }
}
